load("//tools/install:install_data.bzl", "install_data")
load("//tools/lint:lint.bzl", "add_lint_tests")
load(
    "//tools/skylark:drake_cc.bzl",
    "drake_cc_binary",
    "drake_cc_googletest",
    "drake_cc_library",
)
load("//tools/skylark:drake_data.bzl", "models_filegroup")
load(
    "//tools/skylark:drake_py.bzl",
    "drake_py_binary",
    "drake_py_library",
    "drake_py_test",
    "drake_py_unittest",
)

package(default_visibility = ["//visibility:private"])

models_filegroup(
    name = "models",
    visibility = ["//visibility:public"],
)

install_data(
    name = "install_data",
    data = [":models"],
    visibility = ["//visibility:public"],
)

drake_cc_library(
    name = "acrobot_input",
    srcs = ["acrobot_input.cc"],
    hdrs = ["acrobot_input.h"],
    visibility = ["//visibility:public"],
    deps = [
        "//common:dummy_value",
        "//common:essential",
        "//common:name_value",
        "//common/symbolic:expression",
        "//systems/framework:vector",
    ],
)

drake_py_library(
    name = "acrobot_io",
    srcs = ["acrobot_io.py"],
    deps = [
        "//bindings/pydrake",
    ],
)

drake_cc_library(
    name = "acrobot_params",
    srcs = ["acrobot_params.cc"],
    hdrs = ["acrobot_params.h"],
    visibility = ["//visibility:public"],
    deps = [
        "//common:dummy_value",
        "//common:essential",
        "//common:name_value",
        "//common/symbolic:expression",
        "//systems/framework:vector",
    ],
)

drake_cc_library(
    name = "acrobot_state",
    srcs = ["acrobot_state.cc"],
    hdrs = ["acrobot_state.h"],
    visibility = ["//visibility:public"],
    deps = [
        "//common:dummy_value",
        "//common:essential",
        "//common:name_value",
        "//common/symbolic:expression",
        "//systems/framework:vector",
    ],
)

drake_cc_library(
    name = "spong_controller_params",
    srcs = ["spong_controller_params.cc"],
    hdrs = ["spong_controller_params.h"],
    visibility = ["//visibility:public"],
    deps = [
        "//common:dummy_value",
        "//common:essential",
        "//common:name_value",
        "//common/symbolic:expression",
        "//systems/framework:vector",
    ],
)

drake_cc_library(
    name = "acrobot_lcm",
    srcs = ["acrobot_lcm.cc"],
    hdrs = ["acrobot_lcm.h"],
    deps = [
        ":acrobot_state",
        "//lcmtypes:lcmtypes_drake_cc",
        "//systems/framework:leaf_system",
        "//systems/framework:vector",
    ],
)

drake_cc_library(
    name = "acrobot_plant",
    srcs = ["acrobot_plant.cc"],
    hdrs = ["acrobot_plant.h"],
    visibility = ["//visibility:public"],
    deps = [
        ":acrobot_input",
        ":acrobot_params",
        ":acrobot_state",
        "//common:default_scalars",
        "//systems/controllers:linear_quadratic_regulator",
        "//systems/framework",
        "//systems/sensors:rotary_encoders",
    ],
)

drake_cc_library(
    name = "acrobot_geometry",
    srcs = ["acrobot_geometry.cc"],
    hdrs = ["acrobot_geometry.h"],
    visibility = ["//visibility:public"],
    deps = [
        ":acrobot_params",
        ":acrobot_plant",
        "//geometry:geometry_roles",
        "//geometry:scene_graph",
        "//math:geometric_transform",
        "//systems/framework:diagram_builder",
        "//systems/framework:leaf_system",
    ],
)

drake_py_library(
    name = "metrics",
    srcs = ["metrics.py"],
)

drake_cc_library(
    name = "spong_controller",
    srcs = ["spong_controller.cc"],
    hdrs = ["spong_controller.h"],
    visibility = ["//visibility:public"],
    deps = [
        ":acrobot_plant",
        ":spong_controller_params",
        "//common:default_scalars",
        "//math:wrap_to",
        "//systems/controllers:linear_quadratic_regulator",
        "//systems/framework:leaf_system",
        "//systems/framework:vector",
        "//systems/primitives:linear_system",
    ],
)

drake_py_library(
    # This is the library form of spong_sim.py.
    name = "spong_sim_lib_py",
    srcs = ["spong_sim.py"],
    deps = [
        ":acrobot_io",
        "//bindings/pydrake",
    ],
)

drake_py_binary(
    # This is the directly-runnable form of spong_sim.py.
    name = "spong_sim_main_py",
    srcs = ["spong_sim.py"],
    main = "spong_sim.py",
    deps = [
        ":acrobot_io",
        "//bindings/pydrake",
    ],
)

drake_cc_binary(
    name = "spong_sim_main_cc",
    srcs = ["spong_sim.cc"],
    deps = [
        "//common:add_text_logging_gflags",
        "//common:name_value",
        "//common/schema:stochastic",
        "//common/yaml",
        "//examples/acrobot:acrobot_plant",
        "//examples/acrobot:spong_controller",
        "//systems/analysis:simulator",
        "//systems/framework:diagram_builder",
        "//systems/primitives:vector_log_sink",
    ],
)

# Note: This is a development tool for testing LCM communication
# but does not actually provide test coverage as a stand-alone
# executable.
drake_cc_binary(
    name = "acrobot_lcm_msg_generator",
    testonly = 1,
    srcs = ["test/acrobot_lcm_msg_generator.cc"],
    deps = [
        "//lcm",
        "//lcmtypes:lcmtypes_drake_cc",
        "//systems/analysis:simulator",
    ],
)

drake_py_binary(
    name = "optimizer_demo",
    srcs = ["optimizer_demo.py"],
    add_test_rule = True,
    data = [
        ":spong_sim_main_cc",
        ":test/example_stochastic_scenario.yaml",
    ],
    test_rule_args = [
        "--ensemble_size=3",
        "--num_evaluations=3",
    ],
    deps = [
        ":acrobot_io",
        ":metrics",
    ],
)

drake_cc_binary(
    name = "run_lqr",
    srcs = ["run_lqr.cc"],
    add_test_rule = 1,
    test_rule_args = [
        "-simulation_sec=1.0",
        "-realtime_factor=0.0",
    ],
    deps = [
        ":acrobot_geometry",
        ":acrobot_plant",
        "//geometry:drake_visualizer",
        "//systems/analysis:simulator",
        "@gflags",
    ],
)

drake_cc_binary(
    name = "run_lqr_w_estimator",
    testonly = 1,
    srcs = ["run_lqr_w_estimator.cc"],
    add_test_rule = 1,
    test_rule_args = [
        "-simulation_sec=1.0",
        "-realtime_factor=0.0",
    ],
    deps = [
        ":acrobot_geometry",
        ":acrobot_plant",
        "//common/proto:call_python",
        "//geometry:drake_visualizer",
        "//systems/analysis:simulator",
        "//systems/estimators:kalman_filter",
        "//systems/framework:diagram",
        "//systems/primitives:linear_system",
        "//systems/primitives:vector_log_sink",
        "//systems/sensors:rotary_encoders",
        "@gflags",
    ],
)

drake_cc_binary(
    name = "run_passive",
    srcs = ["run_passive.cc"],
    add_test_rule = 1,
    test_rule_args = [
        "-simulation_sec=1.0",
        "-realtime_factor=0.0",
    ],
    deps = [
        ":acrobot_geometry",
        ":acrobot_plant",
        "//geometry:drake_visualizer",
        "//systems/analysis:simulator",
        "//systems/framework:diagram",
        "@gflags",
    ],
)

drake_cc_binary(
    name = "run_swing_up",
    srcs = [
        "run_swing_up.cc",
    ],
    add_test_rule = 1,
    test_rule_args = [
        # N.B. We can't set -simulation_sec here, because the demo program has
        # success criteria that it asserts after the simulation expires.
        "-realtime_factor=0.0",
    ],
    deps = [
        ":acrobot_geometry",
        ":acrobot_plant",
        ":spong_controller",
        ":spong_controller_params",
        "//geometry:drake_visualizer",
        "//solvers:snopt_solver",
        "//systems/analysis:simulator",
        "@gflags",
    ],
)

drake_cc_binary(
    name = "run_swing_up_traj_optimization",
    srcs = ["test/run_swing_up_traj_optimization.cc"],
    # TODO(ggould) Temporarily turned off due to mac test failures, see #10276.
    add_test_rule = 0,
    tags = ["snopt"],
    test_rule_args = ["-realtime_factor=0.0"],
    deps = [
        ":acrobot_geometry",
        ":acrobot_plant",
        "//common:is_approx_equal_abstol",
        "//geometry:drake_visualizer",
        "//planning/trajectory_optimization:direct_collocation",
        "//solvers:snopt_solver",
        "//solvers:solve",
        "//systems/analysis:simulator",
        "//systems/controllers:finite_horizon_linear_quadratic_regulator",
        "//systems/primitives:trajectory_source",
        "@gflags",
    ],
)

drake_cc_binary(
    name = "spong_controller_w_lcm",
    srcs = [
        "spong_controller_w_lcm.cc",
    ],
    add_test_rule = 1,
    test_rule_args = [
        "-time_limit_sec=1.0",
    ],
    deps = [
        ":acrobot_lcm",
        ":acrobot_plant",
        ":spong_controller",
        ":spong_controller_params",
        "//systems/analysis:simulator",
        "//systems/lcm",
        "@gflags",
    ],
)

drake_cc_binary(
    name = "run_plant_w_lcm",
    srcs = ["run_plant_w_lcm.cc"],
    add_test_rule = 1,
    test_rule_args = [
        "-simulation_sec=1.0",
        "-realtime_factor=0.0",
    ],
    test_rule_size = "medium",
    deps = [
        ":acrobot_geometry",
        ":acrobot_lcm",
        ":acrobot_plant",
        "//geometry:drake_visualizer",
        "//systems/analysis:simulator",
        "//systems/controllers:linear_quadratic_regulator",
        "//systems/lcm",
        "@gflags",
    ],
)

drake_py_unittest(
    name = "acrobot_io_test",
    data = [
        ":test/example_scenario.yaml",
    ],
    deps = [
        ":acrobot_io",
        "//bindings/pydrake",
    ],
)

drake_cc_googletest(
    name = "acrobot_plant_test",
    deps = [
        ":acrobot_plant",
        "//common/test_utilities:eigen_matrix_compare",
        "//common/test_utilities:expect_no_throw",
    ],
)

drake_cc_googletest(
    name = "acrobot_geometry_test",
    deps = [
        ":acrobot_geometry",
        ":acrobot_plant",
    ],
)

drake_py_unittest(
    name = "metrics_test",
    deps = [
        ":metrics",
    ],
)

drake_cc_googletest(
    name = "multibody_dynamics_test",
    data = [":models"],
    deps = [
        ":acrobot_plant",
        "//common/test_utilities:eigen_matrix_compare",
        "//multibody/parsing",
    ],
)

drake_py_unittest(
    name = "spong_sim_lib_py_test",
    deps = [
        ":spong_sim_lib_py",
    ],
)

drake_py_test(
    name = "spong_sim_main_py_test",
    srcs = ["test/spong_sim_main_test.py"],
    allow_import_unittest = True,
    data = [
        ":spong_sim_main_py",
        ":test/example_scenario.yaml",
    ],
    main = "test/spong_sim_main_test.py",
    deps = [
        ":acrobot_io",
        "//bindings/pydrake",
    ],
)

drake_py_test(
    name = "spong_sim_main_cc_test",
    srcs = ["test/spong_sim_main_test.py"],
    allow_import_unittest = True,
    args = ["--cc"],
    data = [
        ":spong_sim_main_cc",
        ":test/example_scenario.yaml",
        ":test/example_stochastic_scenario.yaml",
    ],
    main = "test/spong_sim_main_test.py",
    deps = [
        ":acrobot_io",
        "//bindings/pydrake",
    ],
)

add_lint_tests()
